/**
 *    Copyright (C) 2008  Victor Smirnov <aist11@gmail.com>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along
 *    with this program; if not, write to the Free Software Foundation, Inc.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *    See LICENSE.exceptions in the root folder of this project for possible
 *    exceptions
 *
 */

#ifndef _CUBEFS_CORE_MAP_VECTOR_PAGE_SPECIFIC_HPP
#define	_CUBEFS_CORE_MAP_VECTOR_PAGE_SPECIFIC_HPP

#include <cubefs/core/btree.hpp>


namespace cubefs    {
namespace core      {
namespace map       {
namespace vector    {

class page_specific {};

}
}
}
}



namespace cubefs    {
namespace core      {
namespace btree     {

template <typename Base>
struct Strategy<cubefs::core::map::vector::page_specific, Base>: public Base {

    typedef Base                                        base;

    typedef typename base::PageMgr                      PageMgr;

    typedef typename base::Page                         Page;
    typedef typename base::Page::ID                     ID;
    typedef typename base::Transaction                        Transaction;

    typedef typename base::PageTypes                    PageTypes;

    typedef typename base::Key                          Key;
    typedef typename base::Value                        Value;
    

    typedef typename base::NodeBase                    NodeBase;
    typedef typename base::Counters                   Counters;

    typedef typename base::Iterator                   Iterator;

    typedef typename base::NodeDispatcher               NodeDispatcher;
    typedef typename base::RootDispatcher               RootDispatcher;
    typedef typename base::LeafDispatcher               LeafDispatcher;
    typedef typename base::InternalNodeDispatcher         InternalNodeDispatcher;

    typedef typename base::Node2RootMap                 Node2RootMap;
    typedef typename base::Root2NodeMap                 Root2NodeMap;

    static const long Indexes = base::Indexes;

    struct post_split_fn {
        template <typename SrcNode, typename DstNode, typename Start>
        void operator()(SrcNode *src, DstNode *dst, Start start) {
            if (start > 0) {
                dst->set_prefixes(src->map().keys(start - 1));
            }
            else {
                dst->set_prefixes(src->prefixes());
            }
        }
    };

    void post_split(NodeBase* source, NodeBase *dest, Int start, Transaction &txn) {
        post_split_fn fn;
        NodeDispatcher::DispatchSame(source, dest, start, fn);
    }


    struct pre_merge_fn {
        template <typename SrcNode, typename DstNode>
        void operator()(SrcNode *src, DstNode *dst) {
            for (Int i = 0; i < Indexes; i++) {
                Key b0 = dst->map().max_key(i);
                Key b1 = src->prefix(i);
                for (Int c = 0; c < dst->map().size(); c++) {
                    dst->map().key(i,c) = dst->map().key(i, c) + b0 - b1;
                }
            }
        }
    };

    void pre_merge(NodeBase* source, NodeBase *dest, Transaction &txn) {
        pre_merge_fn fn;
        NodeDispatcher::DispatchSame(source, dest, fn);
    }
};

}
}
}

#endif	/* _CUBEFS_CORE_MAP_VECTOR_PAGE_SPECIFIC_HPP */

